/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Servlet;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.logging.Level;
import java.util.logging.Logger;
import Config.Constants;
import DAO.UserDAO;
import General.XMLUtils;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import productJAXB.generate.ProductList;
import productJAXB.generate.Products;

/**
 *
 * @author DIEM PHUONG
 */
public class Controller extends HttpServlet {

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        request.setCharacterEncoding("UTF-8");
        // get session
        HttpSession session = request.getSession();
        // get action
        String action = request.getParameter(Constants.BTN_ACTION);
        UserDAO userDAO = new UserDAO();
        String url = Constants.PAGE_INDEX;
        try {
            // account
            if (action.equals(Constants.ACT_ACCOUNT)) {
                session.setAttribute(Constants.ATTR_CURRPAGE, Constants.ATTR_LOGIN);
                url = Constants.PAGE_LOGIN;
                RequestDispatcher rd = request.getRequestDispatcher(url);
                rd.forward(request, response);
            } // log in
            if (action.equals(Constants.ACT_LOGIN)) {
                // get param
                String username = request.getParameter(Constants.PARAM_USERNAME_LOG);
                String password = request.getParameter(Constants.PARAM_PASSWORD_LOG);
                // get info of user
                String[] result = userDAO.login(username, password);
                // check if log in is successful
                if (result[0].equals(Constants.USR_SUCCESSFUL)) {
                    // check if user is active
                    if (result[3].equals(Constants.USR_ACTIVE)) {
                        session.setAttribute(Constants.ATTR_USER, result[1]);
                        session.setAttribute(Constants.ATTR_FULLNAME, result[2]);
                        session.setAttribute(Constants.ATTR_ROLE, result[4]);
                        String user = (String) session.getAttribute(Constants.ATTR_USER);
                        String role = (String) session.getAttribute(Constants.ATTR_ROLE);
                        url = Constants.PAGE_INDEX;
                        if (user != null && role.equals(Constants.ROLE_ADMIN)) {
                            url = Constants.PAGE_MANAGE_PRODUCT;
                            response.sendRedirect("AdminController?action=manageProduct");
                            return;
                        }
                        // check if user is banned
                    } else if (result[3].equals(Constants.USR_BANNED)) {
                        request.setAttribute(Constants.ATTR_LOGIN_ERR, Constants.ATTR_LOGIN_ERR_MESS_BANNED);
                        url = Constants.PAGE_LOGIN;
                    }
                    // if log in is unsuccessful
                } else if (result[0].equals(Constants.USR_FAILED)) {
                    // err --> return to index page
                    request.setAttribute(Constants.ATTR_LOGIN_ERR, Constants.ATTR_LOGIN_ERR_MESS_INVALID);
                    url = Constants.PAGE_INDEX;
                }
                RequestDispatcher rd = request.getRequestDispatcher(url);
                rd.forward(request, response);
            } // Register
            else if (action.equals(Constants.ACT_REGISTER)) {
                // get param
                String username = request.getParameter(Constants.PARAM_USERNAME_REG);
                String password = request.getParameter(Constants.PARAM_PASSWORD_REG);
                String fullname = request.getParameter(Constants.PARAM_FULLNAME);
                String phone = request.getParameter(Constants.PARAM_PHONE);
                String email = request.getParameter(Constants.PARAM_EMAIL);
                String address = request.getParameter(Constants.PARAM_ADDRESS);
                String selectGender = request.getParameter(Constants.PARAM_SELECTGENDER);
                url = Constants.PAGE_LOGIN;
                // var for checking if user is existing or not
                boolean checkUser = userDAO.checkUser(username);
                // check if user is existing
                if (checkUser) {
                    request.setAttribute(Constants.ATTR_USERNAME, Constants.ATTR_USER_EXIST_ERR);
                    // check if user is not existing
                } else {
                    boolean gender = false;
                    if (selectGender.equals(Constants.MALE)) {
                        gender = true;
                    }
                    boolean register = userDAO.register(username, password, fullname, gender, phone, email, address);
                    if (register) {
                        request.setAttribute(Constants.ATTR_REG, Constants.ATTR_REG_SUC_MESS);
                    } else {
                        request.setAttribute(Constants.ATTR_REG, Constants.ATTR_REG_ERR_MESS);
                    }
                }
                RequestDispatcher rd = request.getRequestDispatcher(url);
                rd.forward(request, response);
            } // Log out
            else if (action.equals(Constants.ACT_LOGOUT)) {
                session.invalidate();
                url = Constants.PAGE_INDEX;
                RequestDispatcher rd = request.getRequestDispatcher(url);
                rd.forward(request, response);
            } // Home -- List/Show products
            else if (action.equals(Constants.ACT_HOME)) {
                // marshal product to xml file
                String context = getServletContext().getRealPath(Constants.CONTEXT_REALPATH);
                String filePath = context + Constants.FILEPATH_XML_PRODUCTS;
                Products proList = UserDAO.getAllProducts();
                if (proList != null) {
                    XMLUtils.marshallClass(proList, filePath);
                    session.setAttribute(Constants.ATTR_CURRPAGE, Constants.ATTR_HOMEPAGE);
                    url = Constants.PAGE_MAIN;
                    RequestDispatcher rd = request.getRequestDispatcher(url);
                    rd.forward(request, response);
                }
            } // Search by name/brand using XPath with DOMTree
            else if (action.equals(Constants.ACT_SEARCH)) {
                // get param
                String key = request.getParameter(Constants.PARAM_SEARCH_KEY);
                // set session attribute
                session.setAttribute(Constants.ATTR_CURRPAGE, Constants.ATTR_SEARCHPAGE);
                session.setAttribute(Constants.ATTR_SEARCH_KEY, key);
                // if key = blank or null --> error
                if (key.equals(Constants.BLANK_VALUE) || key == null) {
                    request.setAttribute(Constants.ATTR_SEARCH_ERR, Constants.ATTR_SEARCH_ERR_MESS);
                    url = Constants.PAGE_SEARCH;
                    RequestDispatcher rd = request.getRequestDispatcher(url);
                    rd.forward(request, response);
                }
                // build DOM Tree for search
                String context = getServletContext().getRealPath(Constants.CONTEXT_REALPATH);
                String filePath = context + Constants.FILEPATH_XML_PRODUCTS;
                Document doc = XMLUtils.buildDOMTree(filePath);
                XPathFactory xpf = XPathFactory.newInstance();
                XPath xpath = xpf.newXPath();
                //String exp = "//product[contains(productName, '" + key + "')]";
                String exp = "//product[productName[contains(translate(text(),'aăâbcdđeêghiklmnoôơpqrstuưvxyzwàáâãèéêìíòóôõùúĩũơưạảấầẩẫậắằẳẵặẹẻẽềềểễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰửữựỳỵỷỹ','AĂÂBCDĐEÊGHIKLMNOÔƠPQRSTUƯVXYZWÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĨŨƠƯẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪỲỴÝỶỸ'),translate('" + key + "','aăâbcdđeêghiklmnoôơpqrstuưvxyzwàáâãèéêìíòóôõùúĩũơưạảấầẩẫậắằẳẵặẹẻẽềềểễệỉịọỏốồổỗộớờởỡợụủứừỬỮỰửữựỳỵỷỹ ','AĂÂBCDĐEÊGHIKLMNOÔƠPQRSTUƯVXYZWÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĨŨƠƯẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼỀỀỂỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪỲỴÝỶỸ'))]]";
                // result will be return with nodeList
                NodeList result = (NodeList) xpath.evaluate(exp, doc, XPathConstants.NODESET);
                // if result is empty --> error
                if (result != null) {
                    // transfer to list of product for showing
                    List products = new ArrayList();
                    for (int i = 0; i < result.getLength(); i++) {
                        Node node = result.item(i);
                        ProductList product = new ProductList();
                        String productID = node.getChildNodes().item(1).getTextContent();
                        String productName = node.getChildNodes().item(3).getTextContent();
                        String categoryID = node.getChildNodes().item(5).getTextContent();
                        String price = node.getChildNodes().item(7).getTextContent();
                        String productImg = node.getChildNodes().item(9).getTextContent();
                        String description = node.getChildNodes().item(11).getTextContent();
                        String proIsShow = node.getChildNodes().item(13).getTextContent();
                        String quantityInStock = node.getChildNodes().item(15).getTextContent();
                        // add product
                        product.setProductID(new BigInteger(Integer.valueOf(productID).toString()));
                        product.setProductName(productName);
                        product.setCategoryID(new BigInteger(Long.valueOf(categoryID).toString()));
                        product.setPrice(new BigInteger(Long.valueOf(price).toString()));
                        product.setProductImg(productImg);
                        product.setDescription(description);
                        if (proIsShow.equals(Constants.BOOL_TRUE)) {
                            product.setIsShow(true);
                        } else {
                            product.setIsShow(false);
                        }
                        product.setQuantityInStock(new BigInteger(Integer.valueOf(quantityInStock).toString()));
                        products.add(product);
                    }
                    // in case of empty list
                    if (products.isEmpty()) {
                        request.setAttribute(Constants.ATTR_SEARCH_ERR, Constants.ATTR_SEARCH_ERR_MESS);
                        // in case of finding product
                    } else {
                        request.setAttribute(Constants.ATTR_SEARCH_RESULT, products);
                    }
                } // in case result is empty
                else {
                    request.setAttribute(Constants.ATTR_SEARCH_ERR, Constants.ATTR_SEARCH_ERR_MESS);
                }
                url = Constants.PAGE_SEARCH;
                RequestDispatcher rd = request.getRequestDispatcher(url);
                rd.forward(request, response);
            } // account detail
            else if (action.equals(Constants.ACT_ACCOUNTDETAIL)) {
                url = Constants.PAGE_ACCOUNTDETAIL;
                RequestDispatcher rd = request.getRequestDispatcher(url);
                rd.forward(request, response);
            } // view account detail
            else if (action.equals(Constants.ACT_VIEWACCOUNTDETAIL)) {
                // get accountDetail -- string type, split by ;
                String username = (String) session.getAttribute(Constants.ATTR_USER);
                String accountInfo = userDAO.accountInfo(username);
                // get accountInfo has occurred error
                if (accountInfo.equals(Constants.BLANK_VALUE) || accountInfo == null) {
                    accountInfo = Constants.MESS_VIEWACCOUNTDETAIL_ERR;
                }
                response.setContentType("text/plain");
                response.setCharacterEncoding("UTF-8");
                out.write(accountInfo);
            } // update account detail
            else if (action.equals(Constants.ACT_UPDATEACCOUNTDETAIL)) {
                String username = (String) session.getAttribute(Constants.ATTR_USER);
                String phone = request.getParameter(Constants.PARAM_PHONE);
                String email = request.getParameter(Constants.PARAM_EMAIL);
                String address = request.getParameter(Constants.PARAM_ADDRESS);
                String accountInfo = userDAO.updateAccountInfo(username, phone, email, address);
                // email field required
                if (email.equals(Constants.BLANK_VALUE) || email == null) {
                    accountInfo = Constants.MESS_UPDATEACCOUNTDETAIL_ERR_BLANKEMAIL;
                }
                // update accountInfo has occurred error
                if (accountInfo.equals(Constants.BLANK_VALUE) || accountInfo == null) {
                    accountInfo = Constants.MESS_UPDATEACCOUNTDETAIL_ERR;
                }
                response.setContentType("text/plain");
                response.setCharacterEncoding("UTF-8");
                out.write(accountInfo);
            } // change password
            else if (action.equals(Constants.ACT_CHANGEPASSWORD)) {
                // get param
                String oldPwd = request.getParameter(Constants.PARAM_OLDPASS);
                String newPwd = request.getParameter(Constants.PARAM_NEWPASS);
                String mess = Constants.BLANK_VALUE;
                if (oldPwd == null || newPwd == null) {
                    mess = Constants.MESS_CHANGEPASS_ERR_BLANK;
                } else {
                    String username = (String) session.getAttribute(Constants.ATTR_USER);
                    boolean result = userDAO.changePassword(username, oldPwd, newPwd);
                    if (result) {
                        mess = Constants.MESS_CHANGEPASS_SUCCESS;
                    } else {
                        mess = Constants.MESS_CHANGEPASS_ERR_MISSMATCH;
                    }
                }
                response.setContentType("text/plain");
                response.setCharacterEncoding("UTF-8");
                out.write(mess);
            }


        } catch (Exception e) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, e);
        } finally {
            out.close();
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
